package com.pointcircle.core.web.annotation;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;

import com.pointcircle.core.BusinessException;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public abstract class AbstractCriteriaOperator {
	
	private String name;
	
	public AbstractCriteriaOperator(String name) {
		if(StringUtils.isEmpty(name)) {
			throw new BusinessException("AbstractCriteriaOperator of " + this.getClass().getName() + " : the name is null! ");
		}
		this.name = name.toLowerCase();
	}
	
	public Predicate getPredicate(CriteriaBuilder cb, Root<?> root, String[] fields, Object value) {
		List<Predicate> list = new LinkedList<Predicate>();
		for(String field : fields) {
			list.add(this.getPredicate(cb, root, field, value));
		}
		Predicate[] predicates = list.toArray(new Predicate[list.size()]);
		return cb.or(predicates);
	}
	
	public Predicate getPredicate(CriteriaBuilder cb, Root<?> root, String field, Object value) {
		String[] fields = StringUtils.split(field, ".");
		if(fields.length > 1) {
			@SuppressWarnings("rawtypes")
			Join join = null;
			for(int i = 0; i < fields.length - 1; i++) {
				if(join == null) {
					join = root.join(fields[i], JoinType.LEFT);
				} else {
					join = join.join(fields[i], JoinType.LEFT); 
				}
			}
			String lastField = fields[fields.length - 1];
			return createPredicate(cb, join, lastField, value);
		} else {
			return createPredicate(cb, root, field, value);
		}
	}
	
	@SuppressWarnings("rawtypes")
	public abstract Predicate createPredicate(CriteriaBuilder cb, From from, String field, Object value);
}
